#include "gpio.h"
#include <iostream>
#include "esm6800_drivers.h"
#include <unistd.h>
#include "can_app.h"
#include "Serial.h"
#include <signal.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>

#include <execinfo.h>

#include "can_uim.h"
#include "msg_def.h"
#include "wontec_wt184.h"
#include "rs485.h"
#include "procedure.h"
#include "board_data_proc.h"

//#define msgQueueKeyPath "/home/usr/msg/msg.tmp"

using namespace std;

CCan * g_canHandle_can0 = NULL;
CCan * g_canHandle_can1 = NULL;

CUim_MainCtl  * g_uimCanHandle = NULL;
CCan * g_subBoardCanHandle = NULL;

CRs485 * g_ptrRs485WT = NULL;


extern pthread_mutex_t mutex_recvBuff;

extern pthread_mutex_t mutex_uim_devs;
extern pthread_mutex_t mutex_uim_frames;

extern ob_manage * g_ptrObManage;

int g_exitFlag = 0;

int g_msg_id = 0;

extern CDataFile * g_fileCapData;

int g_msg_id_Q1 = 0;

int g_msg_id_lua = 0;

#define BACKTRACE_SIZE   16

void dump(void)
{
        int j, nptrs;
        void *buffer[BACKTRACE_SIZE];
        char **strings;

        nptrs = backtrace(buffer, BACKTRACE_SIZE);

        printf("backtrace() returned %d addresses\n", nptrs);

        strings = backtrace_symbols(buffer, nptrs);
        if (strings == NULL) {
                perror("backtrace_symbols");
                exit(EXIT_FAILURE);
        }

        for (j = 0; j < nptrs; j++)
                printf("  [%02d] %s\n", j, strings[j]);

        free(strings);
}


void handler(int data)
{ 
    printf("sig is %d\n", data);
    if(data == SIGSEGV)
    {
        printf("\n=========>>>catch signal %d <<<=========\n", data);

        printf("Dump stack start...\n");
        dump();
        printf("Dump stack end...\n");

        signal(data, SIG_DFL); //对该信号进行默认处理 
        raise(data);           // 向自身发信号 
        return;
    }
    
    if(g_canHandle_can0)
    {
       g_canHandle_can0->CloseCanPort(); 
    }

    if(g_canHandle_can1)
    {
       g_canHandle_can1->CloseCanPort(); 
    }

    pthread_mutex_destroy(&mutex_recvBuff);

    g_exitFlag = 1;

    system("exit 0");
}

extern FILE * g_fp_z;

//gpio0--gpio9
//gpio14--gpio22
#define GPIO_TOTEST 0x007fC3ff


int main(int argc, char * argv[])
{
     CGpio * gpioHandle = CGpio::getInstance();
     unsigned int pinState = 0xffffffff;  
    int ret = 0;  

    ret = gpioHandle->GPIO_OutEnable(0xffffffff);
    //cout<<"OutEnable GPIO0 ret:"<<ret<<endl;    
    //ret = gpioHandle->GPIO_OutEnable(GPIO15);

    ret = gpioHandle->GPIO_OutSet(GPIO15);
    // cout<<"OutSet GPIO0 ret:"<<ret<<endl;
    // gpioHandle->GPIO_OutSet(GPIO1);
    
    // sleep(1);
    // gpioHandle->GPIO_PinState(&pinState);
    // cout<<"pin state is:0x"<<hex<<pinState<<endl;

    CSerial ttyS1;
    ret = ttyS1.OpenPort( 1, 115200, '8', '1', 'N');

    if(ret<0)
    {
        cout<<"serial ttyS1 open fail"<<endl;
		return -1;
    }
    //setting can start
    pthread_mutex_init(&mutex_recvBuff,NULL); 
    pthread_mutex_init(&mutex_uim_devs,NULL);
    pthread_mutex_init(&mutex_uim_frames,NULL);

    //-------the following is for setting uim------
    CUim_MainCtl can0;   



    key_t key = ftok(msgQueueKeyPath, 0x1234);
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }

    int msg_id = msgget(key, IPC_CREAT);
    if(msg_id < 0)
    {
        perror("msgget");
    }

    can0.setKeyId_FrameMQ(msg_id);
    can0.setType_MQ(QUEUE_MSG_TYPE_UIM);

    can0.OpenCanPort(0,NULL);
#ifdef _QPCR
    can0.findDevsInNet();
#endif
    
#ifndef _QPCR
    can0.initTecan();
#endif

    //-------the above is for setting uim------

    //-------the following is for setting ele ctl board------

    filter_array filtersCan1;

    filtersCan1.num = 1;
    filtersCan1.filters[0].can_id = 0x4ff;
    filtersCan1.filters[0].can_mask = 0x400;
    
    CCan can1;

    //key_t key = ftok("msg.tmp", 0x1234);
    // if(key < 0)
    // {
    //     perror("ftok");
    //     return -1;
    // }

    // int msg_id = msgget(key, IPC_CREAT);
    // if(msg_id < 0)
    // {
    //     perror("msgget");
    // }

    can1.setKeyId_FrameMQ(msg_id);
    can1.setType_MQ(QUEUE_MSG_TYPE_BOARDS);

    can1.OpenCanPort(1,&filtersCan1);
    //-------the above is for settting lec------
    g_canHandle_can0 = &can0;
    g_canHandle_can1 = &can1;
    //can setting end

    g_uimCanHandle = &can0;
    g_subBoardCanHandle = &can1;
    //setting for rs485 here----
#ifndef _QPCR
     CRs485 rs485WT;
     serialConfig wt485Config;
     wt485Config.baudrate = 115200;
     wt485Config.databits = '8';
     wt485Config.parity = 'N';
     wt485Config.stopbits = '1';
     rs485WT.setQueueMsgId(msg_id);
     rs485WT.openPort(RS485_TTYS_NUM,RTS_IO,&wt485Config);

     g_ptrRs485WT = &rs485WT;
#endif    
    //setting for rs485 end----

    signal(SIGINT, handler);
    signal(SIGKILL, handler);
    signal(SIGTERM, handler);
    signal(SIGSEGV, handler);

    ob_manage * ptrObManage = new ob_manage();
    g_ptrObManage = ptrObManage;
    ptrObManage->start();
    g_exitFlag = 0;
    g_fileCapData = NULL;
    startSampleThread();

    g_fp_z = NULL;

    g_msg_id_Q1 = 0;
    g_msg_id_lua = -1;

#ifdef _QPCR
    key = ftok(msgQueueKeyQ1Path, keyMsg_QPCR1);
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }

    msg_id = msgget(key, IPC_CREAT);
    if(msg_id < 0)
    {
        perror("msgget");
    }

    g_msg_id_Q1 = msg_id;
#endif
    int testGpio = 0;
    int cntTestGpio = 0;
    while(!g_exitFlag)
    {
       sleep(1);
#if 0
#ifndef _QPCR
       cntTestGpio++;
       //pinState = 0xffffffff;
       //gpioHandle->GPIO_PinState(&pinState);
       if(cntTestGpio >= 5)
       {
            cntTestGpio = 0;
       }
       else
       {
           continue;
       }
       
       if(testGpio)
       {
           ret = gpioHandle->GPIO_OutSet(GPIO_TOTEST);
           testGpio = 0;
           std::cout<<"main, set gpio15"<<std::endl;

           if(ret<0)
           {
               std::cout<<"set gpio15 failed"<<std::endl;
           }
       }
       else
       {
           ret = gpioHandle->GPIO_OutClear(GPIO_TOTEST);
           testGpio = 1;
           std::cout<<"main, clear gpio15"<<std::endl;
           if(ret<0)
           {
               std::cout<<"clear gpio15 failed"<<std::endl;
           }
       }      
#endif
#endif
       //cout<<"pin state is:0x"<<hex<<pinState<<",VH_back:"<<GET_VH_Back(pinState)<<endl;
    }

    if(ptrObManage!=NULL)
    {
        delete ptrObManage;
        ptrObManage = NULL;
    }
    
}
